/**
 * 每个节点都去找自己的父级，根据对象的引用特性，都会同步变化
 * @param {*} list 扁平列表数据{id,name,parentId}
 * @param {*} rootId  根节点的 parentId值，默认为 null
 * @returns 树结构是有children层级
 */
function listToTree(list, rootId=null) {
  const tree = [];
  const map = {};
  // 初始化树结构查询表
  for(let item of list) {
    map[item.id] = {...item,children:[]};
  }
  for(let node of list) {
    if(node.parentId === rootId) {
      tree.push(map[node.id]); //找到根结点
    } else {
      const parentNode = map[node.parentId];
      parentNode && parentNode.children.push(map[node.id])
    }
  }
  return tree;
}
const list = [
  { id: 1, name: '部门A', parentId: null },
  { id: 2, name: '部门B', parentId: 1 },
  { id: 3, name: '部门C', parentId: 1 },
  { id: 4, name: '部门D', parentId: 2 },
  { id: 5, name: '部门E', parentId: null },
];

const tree = listToTree(list);
console.log(JSON.stringify(tree, null,2));